<%
	-- Copyright 2018-2020 Lienol <lawlienol@gmail.com>
	local api = require "luci.model.cbi.passwall.api.api"
	local dsp = require "luci.dispatcher"
	
	local tcp_node_num = api.uci_get_type("global_other", "tcp_node_num", 1)
	local udp_node_num = api.uci_get_type("global_other", "udp_node_num", 1)
	local compact_display_nodes = api.uci_get_type("global_other", "compact_display_nodes", 1)
-%>

<style>
table th, .table .th {
	text-align: center;
}

table td, .table .td {
	text-align: center;
    white-space: nowrap;
    word-break: keep-all;
}

#set_node_div {
	display: none;
	width: 30rem;
	position: fixed;
	top:50%;
	padding-top: 30px;
	z-index: 99;
	text-align: center;
	background: white;
    box-shadow: darkgrey 10px 10px 30px 5px;
}

._select {
	background: #dad8d8;
}
</style>

<script type="text/javascript">
	//<![CDATA[
	var ajax = {
		post: function(url, data, fn_success, timeout, fn_timeout) {
			var xhr = new XMLHttpRequest();
			var code = ajax.encode(data);
			xhr.open("POST", url, true);
			xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
			
			if (timeout && timeout > 1000) {
				xhr.timeout = timeout;
			}
			if (fn_timeout) {
				xhr.ontimeout = function() {
					fn_timeout(xhr);
				}
			}
			xhr.onreadystatechange = function() {
				if(xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
					var json = null;
					if (xhr.getResponseHeader("Content-Type") == "application/json") {
						try {
							json = eval('(' + xhr.responseText + ')');
						}
						catch(e) {
							json = null;
						}
					}
					fn_success(xhr, json);
				}
			};
			xhr.send(code);
		},
		encode: function(obj) {
			obj = obj ? obj : { };
			obj['_'] = Math.random();

			if (typeof obj == 'object')
			{
				var code = '';
				var self = this;

				for (var k in obj)
					code += (code ? '&' : '') +
						k + '=' + encodeURIComponent(obj[k]);

				return code;
			}

			return obj;
		}
	}
	
	var section = "";
	function open_set_node_div(cbi_id) {
		section = cbi_id;
		document.getElementById("set_node_div").style.display="block";
		var node_name = document.getElementById("cbid.passwall." + cbi_id + ".remarks").value;
		document.getElementById("set_node_name").innerHTML = node_name;
	}
	
	function close_set_node_div() {
		document.getElementById("set_node_div").style.display="none";
		document.getElementById("set_node_name").innerHTML = "";
	}
	
	function _cbi_row_top(id) {
		var dom = document.getElementById("cbi-passwall-" + id);
		if (dom) {
			var trs = document.getElementById("cbi-passwall-nodes").getElementsByClassName("cbi-section-table-row");
			if (trs && trs.length > 0) {
				for (var i = 0; i < trs.length; i++) {
					var up = dom.getElementsByClassName("cbi-button-up");
					if (up) {
						cbi_row_swap(up[0], true, 'cbi.sts.passwall.nodes');
					}
				}
			}
		}
	}
	
	function select_node_div(btn, id) {
		btn.value = "<%:DeSelect%>";
		btn.setAttribute("onclick", "deselect_node_div(this, '" + id + "')");
		var dom = document.getElementById("cbi-passwall-" + id);
		if (dom) {
			dom.classList.add("_select");
			dom.setAttribute("nodes_id", id);
		}
	}
	
	function deselect_node_div(btn, id) {
		btn.value = "<%:Select%>";
		btn.setAttribute("onclick", "select_node_div(this, '" + id + "')");
		var dom = document.getElementById("cbi-passwall-" + id);
		if (dom) {
			dom.classList.remove("_select");
			dom.removeAttribute("nodes_id");
		}
	}
	
	function select_all(btn) {
		var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("cbi-section-table-row");
		if (doms && doms.length > 0) {
			for (var i = 0 ; i < doms.length; i++) {
				var id = doms[i].id.replace("cbi-passwall-", "");
				var btn2 = document.getElementById("select_" + id);
				select_node_div(btn2, id);
			}
			btn.value = "<%:DeSelect all%>";
			btn.setAttribute("onclick", "deselect_all(this)");
		}
	}
	
	function deselect_all(btn) {
		var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("cbi-section-table-row");
		if (doms && doms.length > 0) {
			for (var i = 0 ; i < doms.length; i++) {
				var id = doms[i].id.replace("cbi-passwall-", "");
				var btn2 = document.getElementById("select_" + id);
				deselect_node_div(btn2, id);
			}
			btn.value = "<%:Select all%>";
			btn.setAttribute("onclick", "select_all(this)");
		}
	}
	
	function delete_select_nodes() {
		var doms = document.getElementsByClassName("_select");
		if (doms && doms.length > 0) {
			var ids = [];
			for (var i = 0 ; i < doms.length; i++) {
				if (doms[i].getAttribute("nodes_id")) {
					ids.push(doms[i].getAttribute("nodes_id"))
				}
			}
			if (confirm('<%:Are you sure to delete select nodes?%>') == true){
				XHR.get('<%=dsp.build_url("admin/vpn/passwall/delete_select_nodes")%>', {
					ids: ids.join()
				},
				function(x, data) {
					if(x && x.status == 200) {
						window.location.href = '<%=dsp.build_url("admin/vpn/passwall/node_list")%>';
					}
					else {
						alert("<%:Error%>");
					}
				});
			}
		} else {
			alert("<%:You no select nodes !%>");
		}
	}
	
	function set_node(protocol,number) {
		if (confirm('<%:Are you sure set to%> ' + protocol.toUpperCase() + "_" + number + '<%:the server?%>')==true){
			window.location.href = '<%=dsp.build_url("admin/vpn/passwall/set_node")%>?protocol=' + protocol + '&number=' + number + '&section=' + section;
		}
	}
	
	function get_address_full(id) {
		<% if compact_display_nodes and tonumber(compact_display_nodes) == 1 then %>
			var remarks = document.getElementById("cbid.passwall." + id + ".remarks").value;
			var result = remarks.match("\\（(.+?)\\）");
			if (result != null) {
				var full = result[1];
				var address = full.substring(0, full.lastIndexOf(":"));
				var port = full.substring(full.lastIndexOf(":") + 1);
			}
		<% else %>
			try {
				var address = document.getElementById("cbid.passwall." + id + ".address").value;
				var port = document.getElementById("cbid.passwall." + id + ".port").value;
			}
			catch(err){}
		<% end %>
		//判断是否含有汉字
		var reg = new RegExp("[\\u4E00-\\u9FFF]+","g");
		if ((address != null && address != "") && (port != null && port != "") && reg.test(address) == false && (address.indexOf(".") != -1 && address.charAt(address.address - 1) != ".")) {
			return { address: address, port: port };
		} else {
			return null;
		}
	}
	
	function ping_node(cbi_id, dom) {
		var full = get_address_full(cbi_id);
		if (full != null) {
			XHR.get('<%=dsp.build_url("admin/vpn/passwall/ping_node")%>', {
					address: full.address,
					port: full.port
				},
				function(x, result) {
					if(x && x.status == 200) {
						if (result.ping == null || result.ping.trim() == "") {
							dom.outerHTML = "<font style='color:red'><%:Timeout%></font>";
						} else {
							var ping = parseInt(result.ping);
							if (ping < 100)
								dom.outerHTML = "<font style='color:green'>" + result.ping + " ms" + "</font>";
							else if (ping < 200)
								dom.outerHTML = "<font style='color:#fb9a05'>" + result.ping + " ms" + "</font>";
							else if (ping >= 200)
								dom.outerHTML = "<font style='color:red'>" + result.ping + " ms" + "</font>";
						}
					}
				}
			);
		}
	}
	
	/* 自动Ping */
	var nodes = [];
	const auto_ping_value = document.getElementsByClassName('auto_ping_value');
	for (var i = 0; i < auto_ping_value.length; i++) {
		var cbi_id = auto_ping_value[i].getAttribute("cbiid");
		var full = get_address_full(cbi_id);
		if (full != null) {
			var flag = false;
			//当有多个相同地址和端口时合在一起
			for (var j = 0; j < nodes.length; j++) {
				if (nodes[j].address == full.address && nodes[j].port == full.port) {
					nodes[j].indexs = nodes[j].indexs + "," + i;
					flag = true;
					break;
				}
			}
			if (flag)
				continue;
			nodes.push({
				indexs: i + "",
				address: full.address,
				port: full.port
			});
		}
	}
	
	const _xhr = (index) => {
		return new Promise((res) => {
			const dom = nodes[index];
			if (!dom) res()
			ajax.post('<%=dsp.build_url("admin/vpn/passwall/ping_node")%>', {
					index: dom.indexs,
					address: dom.address,
					port: dom.port
				},
				function(x, result) {
					if (x && x.status == 200) {
						var strs = dom.indexs.split(",");
						for (var i = 0; i < strs.length; i++) {
							if (result.ping == null || result.ping.trim() == "") {
								auto_ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
							} else {
								var ping = parseInt(result.ping);
								if (ping < 100)
									auto_ping_value[strs[i]].innerHTML = "<font style='color:green'>" + result.ping + " ms" + "</font>";
								else if (ping < 200)
									auto_ping_value[strs[i]].innerHTML = "<font style='color:#fb9a05'>" + result.ping + " ms" + "</font>";
								else if (ping >= 200)
									auto_ping_value[strs[i]].innerHTML = "<font style='color:red'>" + result.ping + " ms" + "</font>";
							}
						}
					}
					res();
				},
				5000,
				function(x) {
					var strs = dom.indexs.split(",");
					for (var i = 0; i < strs.length; i++) {
						auto_ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
					}
					res();
				}
			);
		})
	}
	
	let task = -1;
	const thread = () => {
		task = task + 1
		if (nodes[task]) {
			_xhr(task).then(thread);
		}
	}
	for (let i = 0; i < 20; i++) {
		thread()
	}
	
	/* 递归单请求方法
	var index = 0;
	function auto_ping() {
		if (index >= nodes.length) {
			return;
		}
		var indexs = nodes[index].indexs;
		var address = nodes[index].address;
		var port = nodes[index].port;
		ajax.post('<%=dsp.build_url("admin/vpn/passwall/ping_node")%>', {
				index: indexs,
				address: address,
				port: port
			},
			function(x, result) {
				if (x && x.status == 200) {
					var strs = indexs.split(",");
					for (var i = 0; i < strs.length; i++) {
						if (result.ping == null || result.ping.trim() == "") {
							auto_ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
						} else {
							var ping = parseInt(result.ping);
							if (ping < 100)
								auto_ping_value[strs[i]].innerHTML = "<font style='color:green'>" + result.ping + " ms" + "</font>";
							else if (ping < 200)
								auto_ping_value[strs[i]].innerHTML = "<font style='color:#fb9a05'>" + result.ping + " ms" + "</font>";
							else if (ping >= 200)
								auto_ping_value[strs[i]].innerHTML = "<font style='color:red'>" + result.ping + " ms" + "</font>";
						}
					}
				}
				index++;
				return auto_ping();
			},
			function(x) {
				var strs = indexs.split(",");
				for (var i = 0; i < strs.length; i++) {
					auto_ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
				}
				index++;
				return auto_ping();
			},
		);
	}
	auto_ping();
	*/
	
	var edit_btn = document.getElementById("cbi-passwall-nodes").getElementsByClassName("cbi-button cbi-button-edit");
	for(var i = 0; i < edit_btn.length; i++) {
		try {
			var onclick_str = edit_btn[i].getAttribute("onclick");
			var id = onclick_str.substring(onclick_str.lastIndexOf('/') + 1, onclick_str.length - 1);
			var td = edit_btn[i].parentNode;
			var new_div = "";
			//添加"置顶"按钮到"修改"按钮前
			new_div += '<input class="cbi-button" type="button" value="<%:To Top%>" onclick="_cbi_row_top(\'' + id + '\')"/>&nbsp;&nbsp;';
			//添加"选择"按钮到"修改"按钮前
			new_div += '<input class="cbi-button cbi-button-add" type="button" value="<%:Select%>" id="select_' + id + '" onclick="select_node_div(this, \'' + id + '\')"/>&nbsp;&nbsp;';
			//添加"应用"按钮到"修改"按钮前
			new_div += '<input class="cbi-button cbi-button-apply" type="button" value="<%:Use%>" id="apply_' + id + '" onclick="open_set_node_div(\'' + id + '\')"/>&nbsp;&nbsp;';
			td.innerHTML = new_div + td.innerHTML;
		}
		catch(err) {
			console.error(err);
		}
	}
	
	//]]>
</script>

<div style="display: -webkit-flex; display: flex; -webkit-align-items: center; align-items: center; -webkit-justify-content: center; justify-content: center;">
	<div id="set_node_div">
		<div class="cbi-value"><%:You choose node is:%><span id="set_node_name"></span></div>
		<div class="cbi-value">
			<% if tcp_node_num and tonumber(tcp_node_num) >= 1 then %>
				<% for i = 1, tcp_node_num, 1 do %>
					<input class="cbi-button cbi-button-edit" type="button" onclick="set_node('tcp',<%=i%>)" value="TCP_<%=i%>" />
				<% end %>
			<% end %>
			
			<% if udp_node_num and tonumber(udp_node_num) >= 1 then %>
				<% for i = 1, udp_node_num, 1 do %>
					<input class="cbi-button cbi-button-edit" type="button" onclick="set_node('udp',<%=i%>)" value="UDP_<%=i%>" />
				<% end %>
			<% end %>
			<input class="cbi-button cbi-button-remove" type="button" onclick="close_set_node_div()" value="<%:Close%>" />
		</div>
	</div>
</div>